#ifndef _TRIANGLE_H_
#define _TRIANGLE_H_

#include "Maths.h"
#include "Vertex.h"
#include "Ray.h"

namespace Math{
/**
 * Classe de Triangle, 3 sommets
 *
 * Un triangle est composé de 3 sommets
 */       
class MATH_API Triangle
{
 public:
    /**
     * constructeur par défaut
     */
    Triangle();
    /**
     * construit à partir de 3 Vertex
     * @param v0,v1,v2 les trois sommets, idéalement dans l'ordre des aiguilles d'une montre
     */
    Triangle(Vertex v0,Vertex v1,Vertex v2);

    /**
     * Retourne la normale du triangle(et non la normal des Vertex
     * calculée *clockwise* selon les sommets.
     * @return la normal propre au triangle
     */
    Vector& getNormal();
    
    /**
     * Mélange les normales de deux Triangles pour permettre un smoothing
     * @param o l'autre triangle
     */
    void mixNormals(Triangle& o);
    /**
     * recalcule les normales pour qu'elles soient ajustées au calculs d'interpolation
     */
    void recalcNormals(){
        m_V0.normalize();m_V1.normalize();m_V2.normalize();
        m_nrB = m_V1.getNormal()-m_V0.getNormal();
        m_nrC = m_V2.getNormal()-m_V0.getNormal();
    }

    /**
     * Retourne l'intersection si il y a intersection entre le triangle et le rayon, sinon la distance de l'intersection est -1.0f
     * @param ray le rayon
     * @param distance la distance minimale des intersections précédentes
     * @return vrai si intersection
     */
    bool intersects(Ray &ray, float& distance);
    
    /**
     * Intersection à l'infini
     * @param ray le rayon
     * @return vrai si intersection
     */
    bool intersects(Ray &ray);
    
    /**
     * Retourne la normale et l'UV du point d'intersection
     * si les parametres sont non-nuls
     * @param t la distance
     * @param ray le rayon a tester
     * @param normal normale à remplir
     * @param uv vecteur uv à remplir
     */
    virtual void getIntersectionParams(Ray &ray,const float t, Vector *normal, Vector *uv);
    
 private:
    /**
     * Crée la normale a partir des 3 sommets
     * Crée AB' et AC'
     */
    void preCalc();

    Vertex m_V0; ///< Premier sommet
    Vertex m_V1; ///< Deuxième sommet
    Vertex m_V2; ///< Troisième sommet
    Vector m_N0; ///< Normale du 1er sommet
    Vector m_N1; ///< Normale du 2e sommet
    Vector m_N2; ///< Normale du 3e sommet
    Vector m_uv0; ///< Coordonnee UV zero
    Vector m_uvB; ///< Vecteur UV 1-2
    Vector m_uvC; ///< Vecteur UV 1-3
    Vector m_nrB; ///< Vecteur Normal 1-2
    Vector m_nrC; ///< Vecteur Normal 1-3
    Vector m_Normal;///< la normale du plan du triangle
    
    Vector m_ABprime; ///< précalculé, AB'
    Vector m_ACprime;  ///< précalculé, AC'
    float  m_RhoB;  ///< précalculé, AB.dot(AC')
    float  m_RhoC;  ///< précalculé, AC.dot(AB')
}; 

}

#endif
 
